package com.cli.springboot_mdc.config;

import com.cli.springboot_mdc.util.ThreadPoolExecutorMdcWrapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author: xiongmin
 * @since create by 2022/7/15 15:35
 */
@Configuration
public class ThreadPoolConfig {

    @Value("${thread-base-config.corePoolSize:10}")
    private int corePoolSize;

    @Value("${thread-base-config.maxPoolSize:20}")
    private int maxPoolSize;

    @Value("${thread-base-config.queueCapacity:100}")
    private int queueCapacity;

    @Value("${thread-base-config.keepAliveSeconds:120}")
    private int keepAliveSeconds;

    @Bean
    public ThreadPoolExecutorMdcWrapper mdcTestThreadPool() {
        ThreadPoolTaskExecutor threadFactory = new ThreadPoolTaskExecutor();
        threadFactory.setThreadNamePrefix("MDC_TEST-");
        ThreadPoolExecutorMdcWrapper executor = new ThreadPoolExecutorMdcWrapper(
                // 设置核心线程数
                corePoolSize,
                // 设置最大线程数
                maxPoolSize,
                // 设置线程活跃时间（秒）
                keepAliveSeconds,
                // 设置线程活跃时间单位（秒）
                TimeUnit.SECONDS,
                // 设置默认阻塞队列
                new ArrayBlockingQueue<>(queueCapacity),
                // 设置线程工厂
                threadFactory,
                // 设置拒绝策略
                new ThreadPoolExecutor.CallerRunsPolicy()
        );

        return executor;
    }

    @Bean
    public ThreadPoolTaskExecutor demoTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 设置核心线程数
        executor.setCorePoolSize(9);
        // 设置最大线程数
        executor.setMaxPoolSize(20);
        // 设置队列容量
        executor.setQueueCapacity(100);
        // 设置线程活跃时间（秒）
        executor.setKeepAliveSeconds(120);
        // 设置默认线程名称
        executor.setThreadNamePrefix("DEMO_THREAD_POOL-");
        // setWaitForTasksToCompleteOnShutdown（true）该方法就是这里的关键，
        // 用来设置线程池关闭的时候等待所有任务都完成再继续销毁其他的Bean，等待所有任务结束后再关闭线程池
        // 这样这些异步任务的销毁就会先于线程池的销毁。
        // 同时，这里还可以设置setAwaitTerminationSeconds(60)，该方法用来设置线程池中任务的等待时间，
        // 如果超过这个时候还没有销毁就强制销毁，以确保应用最后能够被关闭，而不是阻塞住。
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(180);
        // 设置拒绝策略
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 执行初始化
        executor.initialize();
        return executor;
    }

}
